package com.bestcem.xm.user.service.impl.third;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.user.config.properties.SettingProperties;
import com.bestcem.xm.user.config.properties.WenJuanProperties;
import com.bestcem.xm.user.service.dto.third.WenJuanUserInfoDTO;
import com.bestcem.xm.user.service.third.WenJuanService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 问卷网服务
 *
 * @author qiongyu.cui <qiongyu.cui@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/4 17:48
 */
@Service
@Slf4j
public class WenJuanServiceImpl implements WenJuanService {

    @Resource
    private WenJuanProperties wenJuanProperties;

    @Resource
    private SettingProperties settingProperties;

    @Resource
    private RestTemplate restTemplate;

    private static final String STATUS_CODE = "status_code";
    private static final String ACCESS_TOKEN_KEY = "access_token";
    private static final String SUCCESS_CODE = "1";
    private static final String DATA = "data";

    /*
     * 响应结果：
     * 成功：
     * {
     *     "status": 200,
     *     "status_code": 1,
     *     "data": {
     *         "access_token": "xxxxx"
     *     }
     * }
     *
     * 失败：
     * {
     *     "status": 200,
     *     "status_code": 0,
     *     "err_msg": "参数错误",
     *     "err_code": 10003
     * }
     */
    @Override
    public ServiceResult<String> getToken() {
        // python引用：apps_mysql.user.clients.wjw.WenJuanWangClient.fetch_token
        if (StringUtils.isBlank(wenJuanProperties.getAppKey())
                || StringUtils.isBlank(wenJuanProperties.getSiteName())
                || StringUtils.isBlank(wenJuanProperties.getBaseUrl())) {
            log.error("[User] 请求问卷网服务获取token失败，相关配置信息缺失");
            return ServiceResult.fail("相关配置信息缺失");
        }

        try {
            String token = "";
            // 请求第三方获取token信息
            Map<String, String> param = new HashMap<>();
            param.put("appkey", wenJuanProperties.getAppKey());
            param.put("web_site", wenJuanProperties.getSiteName());
            param.put("timestamp", String.valueOf(System.currentTimeMillis()));
            // 计算签名
            String singature = calcSign(param);
            param.put("signature", singature);
            // 请求token
            ResponseEntity<String> apiResponse = restTemplate.getForEntity(generatorGetUrl(wenJuanProperties.getTokenUrl(), param), String.class);

            // 解析返回内容
            JSONObject response = JSON.parseObject(apiResponse.getBody());
            if (null == response || !response.containsKey(STATUS_CODE)
                    || !String.valueOf(response.get(STATUS_CODE)).equals(SUCCESS_CODE)) {
                log.error("[User] 调用问卷网服务获取token失败");
                return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到token信息");
            }
            token = response.getJSONObject(DATA).getString(ACCESS_TOKEN_KEY);
            return ServiceResult.success(token);
        } catch (Exception e) {
            log.error("[User] 调用问卷网服务获取token失败:{}", e);
            return ServiceResult.fail(ResourceErrorCodeEnum.THIRD_PART, "调用问卷网服务获取token失败！");
        }
    }


    /**
     * /*
     * 获取问卷网用户信息
     * :param code: 账号的的唯一标识
     * :return:
     * 响应结果：
     * 成功：
     * {
     * "status": 200,
     * "status_code": 1,
     * "data": {
     * "mobile": "xxx",
     * "head_img_url": "xxx",
     * "nickname": "xxx",
     * "email": "xxx"
     * "unionid": "xxx"
     * }
     * }
     */
    @Override
    public ServiceResult<WenJuanUserInfoDTO> getUserInfo(String code) {
        // python引用：apps_mysql.user.clients.wjw.WenJuanWangClient.fetch_wen_juan_user
        // 获取问卷网的token
        if (StringUtils.isBlank(code)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "code不能为空！");
        }
        ServiceResult<String> token = getToken();
        if (!token.isSuccess()) {
            return ServiceResult.fail(token.getMsg());
        }

        try {
            // 请求第三方获取用户信息
            Map<String, String> param = new HashMap<>();
            param.put("appkey", wenJuanProperties.getAppKey());
            param.put("web_site", wenJuanProperties.getSiteName());
            param.put("code", code);
            param.put("token", token.getData());
            param.put("timestamp", String.valueOf(System.currentTimeMillis()));
            // 计算签名
            String singature = calcSign(param);
            param.put("signature", singature);
            ResponseEntity<String> apiResponse = restTemplate.getForEntity(generatorGetUrl(wenJuanProperties.getMemberInfoUrl(), param), String.class);
            log.info("问卷网获取用户信息：入参：{}，出参：{}", generatorGetUrl(wenJuanProperties.getMemberInfoUrl(), param), JSON.toJSONString(apiResponse.getBody()));

            // 解析返回内容
            JSONObject response = JSON.parseObject(apiResponse.getBody());
            if (null == response || !response.containsKey(STATUS_CODE)
                    || !String.valueOf(response.get(STATUS_CODE)).equals(SUCCESS_CODE)) {
                return ServiceResult.fail(ResourceErrorCodeEnum.NOT_FOUND, "未查询到用户信息");
            }

            WenJuanUserInfoDTO wenJuanUserInfoDTO = response.getObject(DATA, WenJuanUserInfoDTO.class);
            return ServiceResult.success(wenJuanUserInfoDTO);
        } catch (Exception e) {
            log.error("[User] 调用问卷网服务获取用户信息失败", e);
            return ServiceResult.fail(ResourceErrorCodeEnum.THIRD_PART, "调用问卷网服务获取用户信息失败！");
        }
    }

    /**
     * 计算签名
     * python引用：apps_mysql.user.clients.wjw.WenJuanWangClient.gen_signature
     *
     * @param param 参数
     * @return java.lang.String
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/03/07 16:01
     */
    private String calcSign(Map<String, String> param) {
        String result = "";
        if (!param.isEmpty()) {
            StringBuilder signatureStr = new StringBuilder("");
            param.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEachOrdered(p -> signatureStr.append(p.getValue()));
            signatureStr.append(wenJuanProperties.getAppSecret());
            // md5加密
            result = SecureUtil.md5(signatureStr.toString());
        }
        return result;
    }

    /**
     * 组装最终的get的请求地址，携带参数
     *
     * @param apiUrl     api地址
     * @param queryParam 请求参数
     * @return java.lang.String
     * @author cuiqiongyu <qiongyu.cui@idiaoyan.cn>
     * @date 2022/06/29 11:34
     */
    private String generatorGetUrl(String apiUrl, Map<String, String> queryParam) {
        // 组装请求地址
        StringBuilder urlBuilder = new StringBuilder(apiUrl).append("?");
        for (Map.Entry<String, String> entry : queryParam.entrySet()) {
            urlBuilder.append("&").append(entry.getKey()).append("=").append(entry.getValue());
        }
        return urlBuilder.toString().replaceFirst("&", "");
    }

}
